﻿using System;

namespace Creventive.Wpf.ShellFactory.Utility
{
    /// <summary>
    /// Represents the container of an event which can be garbage collected earlier than a conventional event.
    /// </summary>
    public class WeakEventContainer : WeakEventContainerBase
    {
        /// <summary>
        /// Adds a new listener to this container.
        /// </summary>
        /// <param name="listener">The listener.</param>
        public void AddListener(EventHandler listener)
        {
            if (listener == null)
                throw new ArgumentNullException("listener");
            this.AddListenerCore(listener.Target, listener.Method);
        }

        /// <summary>
        /// Removes the given listener from this container.
        /// </summary>
        /// <param name="listener">The listener.</param>
        public void RemoveListener(EventHandler listener)
        {
            if (listener == null)
                throw new ArgumentNullException("listener");
            this.RemoveListenerCore(listener.Target, listener.Method);
        }

        /// <summary>
        /// Invokes the event using the specified sender and arguments.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="arguments">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        public void Invoke(object sender, EventArgs arguments = null)
        {
            this.InvokeCore(sender, arguments ?? EventArgs.Empty);
        }
    }

    /// <summary>
    /// Represents the container of an event which can be garbage collected earlier than a conventional event.
    /// </summary>
    /// <typeparam name="Targs">The type of the args.</typeparam>
    public class WeakEventContainer<Targs> : WeakEventContainerBase
        where Targs : EventArgs
    {
        /// <summary>
        /// Adds a new listener to this container.
        /// </summary>
        /// <param name="listener">The listener.</param>
        public void AddListener(EventHandler<Targs> listener)
        {
            if (listener == null)
                throw new ArgumentNullException("listener");
            this.AddListenerCore(listener.Target, listener.Method);
        }

        /// <summary>
        /// Removes the given listener from this container.
        /// </summary>
        /// <param name="listener">The listener.</param>
        public void RemoveListener(EventHandler<Targs> listener)
        {
            if (listener == null)
                throw new ArgumentNullException("listener");
            this.RemoveListenerCore(listener.Target, listener.Method);
        }

        /// <summary>
        /// Invokes the event using the specified sender and arguments.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="arguments">The object instance containing the event data.</param>
        public void Invoke(object sender, Targs arguments)
        {
            this.InvokeCore(sender, arguments);
        }
    }
}